package com.fullertontech.framework.dubbo;

import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.context.annotation.DubboComponentScanRegistrar;
import org.apache.dubbo.config.spring.util.BeanRegistrar;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.type.AnnotationMetadata;
import com.fullertontech.framework.global.GlobalUtils;

public class DubboScanConfig extends DubboComponentScanRegistrar{

  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
      BeanDefinitionRegistry registry) {
    Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
    registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
    registerReferenceAnnotationBeanPostProcessor(registry);
  }
  /**
   * Registers {@link ServiceAnnotationBeanPostProcessor}
   *
   * @param packagesToScan packages to scan without resolving placeholders
   * @param registry       {@link BeanDefinitionRegistry}
   * @since 2.5.8
   */
  private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

      BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
      builder.addConstructorArgValue(packagesToScan);
      builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
      AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
      BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);

  }

  private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
      // Register @Reference Annotation Bean Processor
      BeanRegistrar.registerInfrastructureBean(registry,
              ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);

  }

  private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
    Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(GlobalUtils.getMainClassPackageName()));
    return packagesToScan;
  }
  
}
